#include<signal.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;

class Tcp_Server{

  public:
    Tcp_Server(int port)
      :_port(port)
    {}
    void InitServer()
    {
      //创建套接字
      _sockfd = socket(AF_INET,SOCK_STREAM,0);
      if(_sockfd<0)
      {
        cerr<<"socket error"<<endl;
        exit(2);
      }
      cout<<"socket success"<<endl;
      //绑定
      struct sockaddr_in local;
      memset(&local,'\0',sizeof(local));
      local.sin_family = AF_INET; 
      local.sin_port = htons(_port);
      local.sin_addr.s_addr = INADDR_ANY;

      if(bind(_sockfd,(struct sockaddr*)&local,sizeof(local))==-1)
      {
        cerr<<"bind fail"<<endl;
        exit(3);
      }
      cout<<"bind success"<<endl;
      //监听
      if(listen(_sockfd,10)<0)
      {
        cerr<<"listen fail"<<endl;
        exit(4);
      }  

    }

    void Service(int sock,string client_ip,int client_port)
    {
      char buf[1024];
      while(1)
      {
        ssize_t size = read(sock,buf,sizeof(buf)-1);
        if(size>0)//读取成功
        {
          buf[size]='\0';
          cout<<"------------------------------http request begin-----------------"<<endl;
          cout<<buf<<endl;
          cout<<"------------------------------http request end-------------------"<<endl;

          #define PAGE "index.html"
          ifstream in(PAGE);
          if (in.is_open()){
            in.seekg(0, in.end);
            int len = in.tellg();
            in.seekg(0, in.beg);
            char* file = new char[len];
            in.read(file, len);
            in.close();   

          //构建HTTP响应
          string status_line = "http/1.1 200 OK\n"; //状态行
          string response_header = "Content-Length: " + to_string(len) + "\n"; //响应报头
          string blank = "\n"; //空行
          string response_text = file; //响应正文
          string response = status_line + response_header + blank + response_text; //响应报文

          //响应HTTP请求
          send(sock, response.c_str(), response.size(), 0);

          delete[] file;
        }
        }
          else if(size==0)//对端关闭
          {
            cout<<client_ip<<":"<<client_port<<":"<<"close"<<endl;
            break;
          }
          else 
          {
            cerr<<"读取失败"<<endl;
            break;
          }
        }
        close(sock);
      }

      void Start()
      {
        signal(SIGCHLD,SIG_IGN);
        while(1)
        {
          //获取连接
          struct sockaddr_in peer;
          memset(&peer,'\0',sizeof(peer));
          socklen_t len = sizeof(peer);
          int sock=accept(_sockfd,(struct sockaddr*)&peer,&len);
          if(sock<0)
          {
            cerr<<"accept error,continue next"<<endl;
            continue;
          }

          string client_ip = inet_ntoa(peer.sin_addr);
          int client_port = ntohs(peer.sin_port);
          cout<<"get a new link->"<<sock<<" ,"<<client_ip<<" port:"<<client_port<<endl;

          pid_t id=fork();
          if(id==0)
          {
            //子进程处理请求
            Service(sock,client_ip,client_port);
            exit(9);
          } 
        }
      }

      ~Tcp_Server()
      {
        if(_sockfd>=0)
        {
          close(_sockfd);
        }
      }


      private:
      int _sockfd;
      int _port;
    };

    int main(int argc,char* argv[])
    {
      if(argc!=2)
      {
        cout<<"Usage: "<<argv[0]<<" port"<<endl;
        exit(1);
      }

      int port = atoi(argv[1]);
      Tcp_Server* ts = new Tcp_Server(port);
      ts->InitServer(); 
      ts->Start();
      return 0;
    }
